package com.partsoft.dits.integrate;

import java.util.concurrent.Semaphore;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import com.partsoft.dits.ConfigurableBean;
import com.partsoft.dits.DataEdgeDescriptor;
import com.partsoft.dits.DataIntegrateBatch;
import com.partsoft.dits.DataIntegrateProcessor;
import com.partsoft.dits.message.MessageEntity;

/**
 * Spring上下文自动装配的集成引擎
 * TODO 需要重新考虑
 */
public class ContextAutoAssemblyIntegrateReactor extends BaseIntegrateReactor
		implements IntegrateReactor,
		DataIntegrateProcessor,
		ConfigurableBean,
		ApplicationContextAware, 
		ApplicationListener<ApplicationEvent> {
	
	private static final int ALL_SEM = 999999;
	
	private ApplicationContext ownerContext;
	
	private Semaphore initSem = new Semaphore(ALL_SEM); 
	
	public ContextAutoAssemblyIntegrateReactor() {
		initSem.acquireUninterruptibly(ALL_SEM);
	}
	
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		setOwnerContext(context);
	}

	public ApplicationContext getOwnerContext() {
		return ownerContext;
	}
	
	public void setOwnerContext(ApplicationContext ownerContext) {
		this.ownerContext = ownerContext;
	}

	public void finiContext() {
		initSem.acquireUninterruptibly(ALL_SEM);
		synchronized (this) {
			clearDataIntegrateProcessors();
		}
	}
	
	private void loadALLDataIntegrateProcessors() {
		for (DataIntegrateProcessor processor : getOwnerContext().getBeansOfType(DataIntegrateProcessor.class).values()) {
			if (supportIntegrateProcessor(processor)) {
				addDataIntegrateProcessor(processor);
			}
		}
	}

	public void initContext() {
		Assert.notNull(getOwnerContext(), "必须运行在Spring上下文中。");
		synchronized (this) {
			loadALLDataIntegrateProcessors();
		}
		initSem.release(ALL_SEM);
	}
	
	@Override
	public void process(DataIntegrateBatch batch) {
		try {
			initSem.acquire();
			super.process(batch);
		} catch (Throwable e) {
			throw new IllegalArgumentException(e);
		} finally {
			initSem.release();
		}
	}
	
	@Override
	public void process(DataEdgeDescriptor dataDescriptor,
			MessageEntity msgEntity) {
		try {
			initSem.acquire();
			super.process(dataDescriptor, msgEntity);
		} catch (Throwable e) {
			throw new IllegalStateException();
		} finally {
			initSem.release();
		}
	}

	public void onApplicationEvent(ApplicationEvent event) {
		if (getOwnerContext() == null)
			return;
		if (!ObjectUtils.nullSafeEquals(getOwnerContext(), event.getSource()))
			return;
		if (event instanceof ContextRefreshedEvent) {
			initContext();
		} else if (event instanceof ContextStoppedEvent) {
			finiContext();
		}
	}
}
